// Disable warnings about invalid XML
#pragma warning(disable:4635)
#include <WebCore.h>
#pragma warning(default:4635)

#include "WebViewWrapper.h"

namespace AwesomiumDotNet
{
	/// <summary>
	/// An enumeration of the three verbosity settings for the Awesomium Log.
	/// </summary>
	public enum class LogLevel
	{
		/// <summary> No log is created </summary>
		None,
		/// <summary> Logs only errors </summary>
		Normal,
		/// <summary> Logs everything </summary>
		Verbose
	};

	public enum class PixelFormat
	{
		/// <summary> BGRA byte ordering [Blue, Green, Red, Alpha] </summary>
		BGRA,
		/// <summary> RGBA byte ordering [Red, Green, Blue, Alpha] </summary>
		RGBA
	};


	/// <summary>
	/// The WebCore manages the creation of WebViews, the internal worker thread,
	/// and various other global states that are required to embed Chromium.
	/// </summary>
	public ref class WebCore : IDisposable
	{
	private:
		static Awesomium::WebCore* webCore;

	public:
	  /// <summary>
	  /// Instantiates the WebCore.
	  /// </summary>
		WebCore()
		{
			webCore = new Awesomium::WebCore();
		}

	public:
	  /// <summary>
	  /// Instantiates the WebCore.
	  /// </summary>
	  /// <param name="level">
	  /// The logging level to use (default is LogLevel.Normal).
	  /// </param>
		WebCore(LogLevel level)
		{
			webCore = new Awesomium::WebCore((Awesomium::LogLevel)level);
		}

	public:
	  /// <summary>
	  /// Instantiates the WebCore.
	  /// </summary>
	  /// <param name="level">
	  /// The logging level to use (default is LogLevel.Normal).
	  /// </param>
	  /// <param name="enablePlugins">
	  /// Whether or not to enable embedded plugins.
	  /// </param>
		WebCore(LogLevel level, bool enablePlugins)
		{
			webCore = new Awesomium::WebCore((Awesomium::LogLevel)level, enablePlugins);
		}

	public:
	  /// <summary>
	  /// Instantiates the WebCore.
	  /// </summary>
	  /// <param name="level">
	  /// The logging level to use (default is LogLevel.Normal).
	  /// </param>
	  /// <param name="enablePlugins">
	  /// Whether or not to enable embedded plugins.
	  /// </param>
	  /// <param name="pixelFormat">
	  /// The pixel-format/byte-ordering to use when rendering WebViews.
	  /// </param>
		WebCore(LogLevel level, bool enablePlugins, PixelFormat pixelFormat)
		{
			webCore = new Awesomium::WebCore((Awesomium::LogLevel)level,
				enablePlugins, (Awesomium::PixelFormat)pixelFormat);
		}

	public:
	  /// <summary>
	  /// Destroys the WebCore singleton. (Also destroys any lingering WebViews)
	  /// </summary>
		virtual ~WebCore()
		{
			delete webCore;
			webCore = 0;
		}

	public:
	  /// <summary>
	  /// Creates a new WebView.
	  /// </summary>
	  /// <param name="width">
	  /// The width of the WebView in pixels.
	  /// </param>
	  /// <param name="height">
	  /// The height of the WebView in pixels.
	  /// </param>
	  /// <returns>
	  /// Returns a WebView Instance.
	  /// </returns>
		WebView^ CreateWebView(int width, int height)
		{
			return gcnew WebView(webCore, width, height);
		}

	public:
	  /// <summary>
	  /// Creates a new WebView.
	  /// </summary>
	  /// <param name="width">
	  /// The width of the WebView in pixels.
	  /// </param>
	  /// <param name="height">
	  /// The height of the WebView in pixels.
	  /// </param>
	  /// <param name="isTransparent">
	  /// Whether or not the background of a WebView should be rendered as transparent.
	  /// </param>
	  /// <returns>
	  /// Returns a WebView Instance.
	  /// </returns>
		WebView^ CreateWebView(int width, int height, bool isTransparent)
		{
			return gcnew WebView(webCore, width, height, isTransparent);
		}

	public:
	  /// <summary>
	  /// Creates a new WebView.
	  /// </summary>
	  /// <param name="width">
	  /// The width of the WebView in pixels.
	  /// </param>
	  /// <param name="height">
	  /// The height of the WebView in pixels.
	  /// </param>
	  /// <param name="isTransparent">
	  /// Whether or not the background of a WebView should be rendered as transparent.
	  /// </param>
	  /// <param name="enableAsyncRendering">
	  /// Enables fully-asynchronous rendering, see remarks.
	  /// </param>
	  /// <returns>
	  /// Returns a WebView Instance.
	  /// </returns>
	  /// <remark>
	  /// When asynchronous rendering is enabled, all rendering takes place on
	  /// another thread asynchronously. The benefit of this behavior is that you
	  /// may see a marked performance increase on machines with multi-core
	  /// processors (especially when a WebView has high-animation content).
	  /// </remark>
		WebView^ CreateWebView(int width, int height, bool isTransparent, bool enableAsyncRendering)
		{
			return gcnew WebView(webCore, width, height, isTransparent, enableAsyncRendering);
		}

	public:
	  /// <summary>
	  /// Creates a new WebView.
	  /// </summary>
	  /// <param name="width">
	  /// The width of the WebView in pixels.
	  /// </param>
	  /// <param name="height">
	  /// The height of the WebView in pixels.
	  /// </param>
	  /// <param name="isTransparent">
	  /// Whether or not the background of a WebView should be rendered as transparent.
	  /// </param>
	  /// <param name="enableAsyncRendering">
	  /// Enables fully-asynchronous rendering, see remarks.
	  /// </param>
	  /// <param name="maxAsyncRenderPerSec">
	  /// The maximum times per second this WebView should asynchronously render.
	  /// </param>
	  /// <returns>
	  /// Returns a WebView Instance.
	  /// </returns>
	  /// <remark>
	  /// When asynchronous rendering is enabled, all rendering takes place on
	  /// another thread asynchronously. The benefit of this behavior is that you
	  /// may see a marked performance increase on machines with multi-core
	  /// processors (especially when a WebView has high-animation content).
	  /// </remark>
		WebView^ CreateWebView(int width, int height, bool isTransparent, bool enableAsyncRendering, int maxAsyncRenderPerSec)
		{
			return gcnew WebView(webCore, width, height, isTransparent, enableAsyncRendering, maxAsyncRenderPerSec);
		}

	public:
	  /// <summary>
	  /// Sets the base directory.
	  /// </summary>
	  /// <param name="baseDirectory">
	  /// The absolute path to your base directory. The base directory is a 
	  /// location that holds all of your local assets. It will be used for 
	  /// WebView.LoadFile and WebView.LoadHTML (to resolve relative URL's).
	  /// </param>
		void SetBaseDirectory(String^ baseDirectory)
		{
			std::string baseDirectoryString;
			MarshalString(baseDirectory, baseDirectoryString);
			webCore->setBaseDirectory(baseDirectoryString);
		}

	public:
	  /// <summary>
	  /// Retrieves the base directory.
	  /// </summary>
	  /// <returns>
	  /// Returns the current base directory.
	  /// </returns>
		String^ GetBaseDirectory()
		{
			return gcnew String(webCore->getBaseDirectory().c_str());
		}

	public:
	  /// <summary>
	  /// Retrieves the pixel format being used.
	  /// </summary>
		PixelFormat GetPixelFormat()
		{
			return (PixelFormat)webCore->getPixelFormat();
		}

	public:
	  /// <summary>
	  /// Sets a custom response page to use when a WebView encounters a certain
	  /// HTML status code from the server (such as '404 - File not found').
	  /// </summary>
	  /// <param name="statusCode">
	  /// The status code this response page should be associated with.
	  /// See http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
	  /// </param>
	  /// <param name="filePath">
	  /// The local page to load as a response, should be a path relative to the base directory.
	  /// </param>
		void SetCustomResponsePage(int statusCode, String^ filePath)
		{
			std::string filePathString;
			MarshalString(filePath, filePathString);
			webCore->setCustomResponsePage(statusCode, filePathString);
		}

	public:
	  /// <summary>
	  /// Returns whether or not plugins are enabled.
	  /// </summary>
		bool ArePluginsEnabled()
		{
			return webCore->arePluginsEnabled();
		}

	public:
	  /// <summary>
	  /// Updates the WebCore and allows it to conduct various operations such as the propagation
	  /// of bound JS callbacks and the invocation of any queued listener events.
	  /// </summary>
		void Update()
		{
			webCore->update();
		}

	public:
	  /// <summary>
	  /// Pauses the internal thread of the Awesomium WebCore.
	  /// </summary>
	  /// <remarks>
	  /// The pause and resume functions were added as a temporary workaround
	  /// for threading issues with Flash plugins on the Mac OSX platform.
	  /// You should call WebCore::pause right before handling the message loop
	  /// in your main thread (usually via SDL_PollEvents) and immediately call
	  /// resume after.
	  /// </remarks>
		void Pause()
		{
			webCore->pause();
		}

	public:
	  /// <summary>
	  /// Resumes the internal thread of the Awesomium WebCore.
	  /// </summary>
	  /// <seealso cref="Pause"/>
		void Resume()
		{
			webCore->resume();
		}
	};
}
